/*
 * Upstream-Name: Jason MacDuffie
 * Upstream-Contact: taknamay@gmail.com
 * License: GNU GPL v3
 */

import java.awt.*;
import java.text.*;
import java.awt.event.*;
import java.io.*;
import javax.swing.*;

public class CipherBuddy extends JFrame{

// **************
 private JMenuItem openItem, exitItem;
 private JFileChooser chooser;
 private char c;
 private JButton myButton;
 private JLabel promptLabel1, promptLabel2;
 private JTextField inputField1, inputField2;
 private JButton subButton, clearButton, distButton, shiftButton, digramButton, affineButton;  //buttons on monoCard
 private JButton vigSelectSubalphaButton, vigICButton, vigDistButton,
     vigMakeShiftButton, vigCompareButton, vigClearButton; //buttons on vigCard
 private JButton diDigramButton, digramSubButton; //buttons on diCard;
 private JTextArea vigDisplayArea;  //displayarea for vigCard
 private JTextArea colDisplayArea;  //display area for colCard
 private JTextArea diDisplayArea;   //display area for diCard
 private JTextArea outputArea, displayArea;  //display areas for monoCard
 private StringBuffer subString = new StringBuffer("                          ");
 private StringBuffer alphaString = new StringBuffer(
   "a b c d e f g h i j k l m n o p q r s t u v w x y z");
 private StringBuffer cipherText = new StringBuffer("");
 private StringBuffer subText = new StringBuffer("");
 private StringBuffer diSubText = new StringBuffer("");
 private StringBuffer vigSubText = new StringBuffer("");
 private StringBuffer colText = new StringBuffer("");
 private int columns = 0;
 private int vigSubalphabets = 1;
 private JRadioButtonMenuItem monoButton, vigButton, diButton, colButton;
 private ButtonGroup modeGroup;
 private CardLayout cardManager = new CardLayout();
 private JPanel deck, monoCard, vigCard, diCard, colCard;
 private Container container;
 private JScrollPane monoScrollPane, vigScrollPane;
 private JTextField diInputField1,diInputField2,diInputField3,diInputField4;
 private int mode = 0; //0 = mono, 1= vig, 2 = digram, 3 = col
 private File openDirectory = null, saveDirectory = null;
 Color monoColor = new Color(127,255,255);    //color for mono card - aqua
 Color vigColor = new Color(255,255,224);     //color for vigenere card - cream
 Color diColor = new Color(190,255, 190);     //color for digram card - light green
 Color colColor = new Color(255,255,127); //color for columnar card - light yellow

 // constructor **************************************************
    public CipherBuddy() {
      super("CipherBuddy - Mono Substitution");
      
      container = getContentPane();
      
      //set the icon
      setIconImage(HtmlReader.readLocalImage("html/icon.png"));
      
      //set  up menus
      JMenuBar menuBar = new JMenuBar();
      setJMenuBar(menuBar);
      
      //set up file menu ***********************************************
      JMenu fileMenu = new JMenu("File");
      menuBar.add(fileMenu);
      
      //set up file opening menu option
      openItem = new JMenuItem("Open File");
      openItem.addActionListener(
        new ActionListener(){
          public void actionPerformed(ActionEvent event)
          {
             chooser = new JFileChooser(openDirectory); //open with current directory
             int result = chooser.showOpenDialog(container);
             if(result == JFileChooser.APPROVE_OPTION){
               try {
                    readTheFile(chooser.getSelectedFile().getAbsolutePath());
                    openDirectory = chooser.getCurrentDirectory();
                   }
               catch (IOException e) {System.err.println(e.getMessage());}
             }
          }
        }
      );

      //setup save plaintext menu option
      JMenuItem saveItem = new JMenuItem("Save Plaintext");
      saveItem.addActionListener(
        new ActionListener(){
          public void actionPerformed(ActionEvent event)
          {
             chooser = new JFileChooser(saveDirectory); //open with current directory
             int result = chooser.showSaveDialog(container);
             if(result == JFileChooser.APPROVE_OPTION){
               try {
                    saveTheFile(chooser.getSelectedFile().getAbsolutePath());
                    saveDirectory = chooser.getCurrentDirectory();
                   }
            catch (IOException e) {System.err.println(e.getMessage());}
          }
          }
        }
      );
      
      //exit menu option
      exitItem = new JMenuItem("Exit");
      exitItem.setEnabled(true);
      
      exitItem.addActionListener(
        new ActionListener(){
          public void actionPerformed(ActionEvent event)
          {
            System.exit(0);
          }
        }
      );
  
      fileMenu.add(openItem);
      fileMenu.add(saveItem);
      fileMenu.add(exitItem);
      
      // set up mode menu **********************************************
  JMenu modeMenu = new JMenu("Mode");
  menuBar.add(modeMenu);
  
  monoButton = new JRadioButtonMenuItem("Mono Substituion");
  vigButton = new JRadioButtonMenuItem("Vigenere");
  diButton = new JRadioButtonMenuItem("Digram");
  colButton = new JRadioButtonMenuItem("Columnar");
  modeGroup = new ButtonGroup();
  ModeHandler modeHandler = new ModeHandler();
  
  modeMenu.add(monoButton);
  modeMenu.add(vigButton);
  modeMenu.add(diButton);
  modeMenu.add(colButton);
  modeGroup.add(monoButton);
  modeGroup.add(vigButton);
  modeGroup.add(diButton);
  modeGroup.add(colButton);
  
  monoButton.addActionListener(modeHandler);
  vigButton.addActionListener(modeHandler);
  diButton.addActionListener(modeHandler);
  colButton.addActionListener(modeHandler);
  
  monoButton.setSelected(true);

  // The code for the help and about menus were rewritten.
  JMenu helpMenu = new JMenu("Help");
  JMenu aboutMenu = new JMenu("About");
  menuBar.add(helpMenu);
  menuBar.add(aboutMenu);
  
  JMenuItem helpLoadingButton = new JMenuItem("Loading Ciphertext");
  JMenuItem helpEncryptButton = new JMenuItem("Encrypting Messages");
  JMenu helpMonoMenu = new JMenu("Mono substitution");
  JMenuItem helpMonoMakesubButton = new JMenuItem("Make substitution");
  JMenuItem helpMonoLetterButton = new JMenuItem("Letter Distribution and IC");
  JMenuItem helpMonoAffineButton = new JMenuItem("Affine Substitution");
  JMenuItem helpMonoDigramButton = new JMenuItem("Digram Distribution");
  JMenu helpVignereMenu = new JMenu("Vignere");
  JMenuItem helpVignereCompareButton = new JMenuItem("Compare Subalphabets");
  JMenuItem helpVignereKasiskiButton = new JMenuItem("Kasiski Test");
  JMenuItem helpHillButton = new JMenuItem("Hill Cipher");
  JMenuItem helpColumnarButton = new JMenuItem("Columnar");
  
  JMenuItem aboutAboutButton = new JMenuItem("About CipherBuddy");
  
  helpMenu.add(helpLoadingButton);
  helpMenu.add(helpEncryptButton);
  helpMenu.add(helpMonoMenu);
  helpMonoMenu.add(helpMonoMakesubButton);
  helpMonoMenu.add(helpMonoLetterButton);
  helpMonoMenu.add(helpMonoAffineButton);
  helpMonoMenu.add(helpMonoDigramButton);
  helpMenu.add(helpVignereMenu);
  helpVignereMenu.add(helpVignereCompareButton);
  helpVignereMenu.add(helpVignereKasiskiButton);
  helpMenu.add(helpHillButton);
  helpMenu.add(helpColumnarButton);
  
  aboutMenu.add(aboutAboutButton);
  
  helpLoadingButton.addActionListener(
    new ActionListener() {
      public void actionPerformed(ActionEvent event) {
          JFrame window = new JFrame("Loading Ciphertext");
          JPanel panel = new JPanel();
          panel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
          String content = HtmlReader.readLocalFile("html/help_loading.html");
          JLabel label = new JLabel(content);
          panel.add(label, Font.PLAIN);
          window.getContentPane().add(panel);
          window.pack();
          window.setLocationRelativeTo(null);
          window.setResizable(false);
          window.setVisible(true);
      }
    }
  );
  
  helpEncryptButton.addActionListener(
    new ActionListener() {
      public void actionPerformed(ActionEvent event) {
          JFrame window = new JFrame("Encryption");
          JPanel panel = new JPanel();
          panel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
          String content = HtmlReader.readLocalFile("html/help_encryption.html");
          JLabel label = new JLabel(content);
          panel.add(label, Font.PLAIN);
          window.getContentPane().add(panel);
          window.pack();
          window.setLocationRelativeTo(null);
          window.setResizable(false);
          window.setVisible(true);
      }
    }
  );
  
    helpMonoMakesubButton.addActionListener(
    new ActionListener() {
      public void actionPerformed(ActionEvent event) {
          JFrame window = new JFrame("Make substitution");
          JPanel panel = new JPanel();
          panel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
          String content = HtmlReader.readLocalFile("html/help_mono_makesub.html");
          JLabel label = new JLabel(content);
          panel.add(label, Font.PLAIN);
          window.getContentPane().add(panel);
          window.pack();
          window.setLocationRelativeTo(null);
          window.setResizable(false);
          window.setVisible(true);
      }
    }
  );
  
  helpMonoLetterButton.addActionListener(
    new ActionListener() {
      public void actionPerformed(ActionEvent event) {
          JFrame window = new JFrame("Letter Distribution and I.C.");
          JPanel panel = new JPanel();
          panel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
          String content = HtmlReader.readLocalFile("html/help_mono_letter.html");
          JLabel label = new JLabel(content);
          panel.add(label, Font.PLAIN);
          window.getContentPane().add(panel);
          window.pack();
          window.setLocationRelativeTo(null);
          window.setResizable(false);
          window.setVisible(true);
      }
    }
  );

  helpMonoAffineButton.addActionListener(
    new ActionListener() {
      public void actionPerformed(ActionEvent event) {
          JFrame window = new JFrame("Affine Substitution");
          JPanel panel = new JPanel();
          panel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
          String content = HtmlReader.readLocalFile("html/help_mono_affine.html");
          JLabel label = new JLabel(content);
          panel.add(label, Font.PLAIN);
          window.getContentPane().add(panel);
          window.pack();
          window.setLocationRelativeTo(null);
          window.setResizable(false);
          window.setVisible(true);
      }
    }
  );

  helpMonoDigramButton.addActionListener(
    new ActionListener() {
      public void actionPerformed(ActionEvent event) {
          JFrame window = new JFrame("Digram Distribution");
          JPanel panel = new JPanel();
          panel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
          String content = HtmlReader.readLocalFile("html/help_mono_digram.html");
          JLabel label = new JLabel(content);
          panel.add(label, Font.PLAIN);
          window.getContentPane().add(panel);
          window.pack();
          window.setLocationRelativeTo(null);
          window.setResizable(false);
          window.setVisible(true);
      }
    }
  );

  helpVignereCompareButton.addActionListener(
    new ActionListener() {
      public void actionPerformed(ActionEvent event) {
          JFrame window = new JFrame("Compare Subalphabets");
          JPanel panel = new JPanel();
          panel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
          String content = HtmlReader.readLocalFile("html/help_vignere_compare.html");
          JLabel label = new JLabel(content);
          panel.add(label, Font.PLAIN);
          window.getContentPane().add(panel);
          window.pack();
          window.setLocationRelativeTo(null);
          window.setResizable(false);
          window.setVisible(true);
      }
    }
  );

  helpVignereKasiskiButton.addActionListener(
    new ActionListener() {
      public void actionPerformed(ActionEvent event) {
          JFrame window = new JFrame("Kasiski Test");
          JPanel panel = new JPanel();
          panel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
          String content = HtmlReader.readLocalFile("html/help_vignere_kasiski.html");
          JLabel label = new JLabel(content);
          panel.add(label, Font.PLAIN);
          window.getContentPane().add(panel);
          window.pack();
          window.setLocationRelativeTo(null);
          window.setResizable(false);
          window.setVisible(true);
      }
    }
  );

  helpHillButton.addActionListener(
    new ActionListener() {
      public void actionPerformed(ActionEvent event) {
          JFrame window = new JFrame("Hill Cipher");
          JPanel panel = new JPanel();
          panel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
          String content = HtmlReader.readLocalFile("html/help_hill.html");
          JLabel label = new JLabel(content);
          panel.add(label, Font.PLAIN);
          window.getContentPane().add(panel);
          window.pack();
          window.setLocationRelativeTo(null);
          window.setResizable(false);
          window.setVisible(true);
      }
    }
  );

  helpColumnarButton.addActionListener(
    new ActionListener() {
      public void actionPerformed(ActionEvent event) {
          JFrame window = new JFrame("Columnar");
          JPanel panel = new JPanel();
          panel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
          String content = HtmlReader.readLocalFile("html/help_columnar.html");
          JLabel label = new JLabel(content);
          panel.add(label, Font.PLAIN);
          window.getContentPane().add(panel);
          window.pack();
          window.setLocationRelativeTo(null);
          window.setResizable(false);
          window.setVisible(true);
      }
    }
  );

  aboutAboutButton.addActionListener(
    new ActionListener() {
      public void actionPerformed(ActionEvent event) {
          JFrame window = new JFrame("About CipherBuddy");
          JPanel panel = new JPanel();
          panel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
          String content = HtmlReader.readLocalFile("html/about_about.html");
          JLabel label = new JLabel(content);
          panel.add(label, Font.PLAIN);
          window.getContentPane().add(panel);
          window.pack();
          window.setLocationRelativeTo(null);
          window.setResizable(false);
          window.setVisible(true);
      }
    }
  );





/*
      openItem.addActionListener(
        new ActionListener(){
          public void actionPerformed(ActionEvent event)
          {
             chooser = new JFileChooser(openDirectory); //open with current directory
             int result = chooser.showOpenDialog(container);
             if(result == JFileChooser.APPROVE_OPTION){
               try {
                    readTheFile(chooser.getSelectedFile().getAbsolutePath());
                    openDirectory = chooser.getCurrentDirectory();
                   }
               catch (IOException e) {System.err.println(e.getMessage());}
             }
          }
        }
      );

*/


  //end of menu set up *******************************************
  //**************************************************************
      
  //setup deck layout for the 4 different modes
  deck = new JPanel();
  deck.setLayout(cardManager);
  
  
  JPanel monoCard = new JPanel();
  monoCard.setBackground(monoColor);
  deck.add(monoCard,"mono");
  JPanel vigCard = new JPanel();
  vigCard.setBackground(vigColor);
  deck.add(vigCard,"vigenere");
  JPanel diCard = new JPanel();
  diCard.setBackground(diColor);
  deck.add(diCard,"digram");
  JPanel colCard = new JPanel();
  colCard.setBackground(colColor);
  deck.add(colCard,"columnar");
 
 //setup monoCard *************************************
  
 // set up panel for character substitution on monoCard - goes below the text area
        JPanel subPanel = new JPanel();
        subPanel.setLayout(new FlowLayout());
        subPanel.setBackground(monoColor);
        
        promptLabel1 = new JLabel("Cipher char:");
        inputField1 = new JTextField(1);
        
        promptLabel2 = new JLabel("  Plain char:");
        inputField2 = new JTextField(1);
        
        subButton = new JButton("Make Substitution");
        
        subButton.addActionListener(
          new ActionListener(){
            public void actionPerformed(ActionEvent event){
              String s1, s2;
              char pchar, cchar;
              s1 = inputField1.getText();
              s2 = inputField2.getText();
              //only make sub if data entered
              if(s1.length()>0 && s2.length()>0){
                pchar = Character.toLowerCase(s1.charAt(0));
                cchar = Character.toLowerCase(s2.charAt(0));
                makeSub(pchar,cchar);
              }
            }
          }
        );
        
        //make subPanel
        subPanel.add(promptLabel1);
        subPanel.add(inputField1);
        subPanel.add(promptLabel2);
        subPanel.add(inputField2);
        subPanel.add(subButton);
       
 //now setup the display area for ciphertext
 displayArea = new JTextArea(30,100);
 displayArea.setFont(new Font("monospaced",Font.PLAIN,12));
 displayArea.setText("No cipher text loaded.");
     
 //setup area to show substitutions
 outputArea = new JTextArea(2,51);
 outputArea.setFont(new Font("monospaced",Font.PLAIN,12));
 outputArea.setText("\n"+alphaString.toString());
  
  //clear button 
  clearButton = new JButton("Clear Guesses");
        clearButton.addActionListener(
          new ActionListener(){
            public void actionPerformed(ActionEvent event){
              for(int i=0; i<26;i++)
                subString.setCharAt(i,' ');
              ShowSubstitution();
              for(int i=0;i<cipherText.length();i++)
             subText.setCharAt(i,'*');
           ShowText();
          }
          }
        );
        
        //distribution and I.C. button
        distButton = new JButton("Letter Distribution and I.C.");
        distButton.addActionListener(
          new ActionListener(){
            public void actionPerformed(ActionEvent event){
              int[] count = new int[26];
              for(int i=0;i<26; i++) count[i]=0;
              for(int i=0; i<cipherText.length();i++) {
                int c=cipherText.charAt(i)-'a';
                count[c]++;
              }
              String s = new String("");
              String alphabet = new String("abcdefghijklmnopqrstuvwxyz");
              for(int i=0; i<26;i++){
                s = s +  Character.toString(alphabet.charAt(i)) + " " +
                count[i] + "\n";
              }
              //compute ic
             
              double ic=0;
              int total = 0;
              for(int i=0;i<26;i++){
                total += count[i];
                ic += count[i]*(count[i]-1);
              }
              ic = ic/(total*(total -1));
              s += " size = "+total+"\n";
              
        
              DistFrame distFrame =  new DistFrame(ic,s);
           }
          }
        );
        
       //digram distribution button
       digramButton = new JButton("Digram Distribution");
        digramButton.addActionListener(
          new ActionListener(){
            public void actionPerformed(ActionEvent event){
              int[][] diCount = new int[26][26];
              for(int i=0;i<26;i++)
                for(int j=0;j<26;j++)
                  diCount[i][j] = 0;
              int i=0;
              while(i<cipherText.length()-1){
                diCount[cipherText.charAt(i) - 'a'][cipherText.charAt(i+1) - 'a']++;
         //       i += 2;
                i++;
              }
              String s = new String("");
              s = "     A    B    C    D    E    F    G    H    I    J    K    L    M";
              s += "    N    O    P    Q    R    S    T    U    V    W    X    Y    Z\n";
              for(i=0;i<26;i++){
                s+=Character.toString((char)('A' + i));
                for(int j=0;j<26;j++)
                  s +=" " + padOutput(diCount[i][j]) + diCount[i][j];
                  s += "\n";
              }
              double f = 0;
              int total = 0;
              for(i=0; i<26;i++)
                for(int j=0;j<26;j++){
                  f += diCount[i][j]*(diCount[i][j]-1);
                  total += diCount[i][j];
                }
              f /= total*(total-1);
            NumberFormat form = NumberFormat.getInstance(); //format for ic
              form.setMaximumFractionDigits(5);
               
              s += "\n Digram roughness: "+form.format(f)+"\n";
              
              //display
              DigramFrame digramFrame = new DigramFrame(s);
           }
          }
        );
        
        //shift button
        shiftButton = new JButton("Shift Substitution");
        ShiftHandler shiftHandler = new ShiftHandler();
        shiftButton.addActionListener(shiftHandler);

        //affine button
        affineButton = new JButton("Affine Substitution");
        AffineHandler affineHandler = new AffineHandler();
        affineButton.addActionListener(affineHandler);

  // myButton stuff
   myButton = new JButton("My Button");

   myButton.addActionListener(
    new ActionListener(){
     public void actionPerformed(ActionEvent event){
       MyFrame myFrame = new MyFrame();
       //DoSomething();
     }
    }
   );

  //end of myButton stuff
  
        monoScrollPane = new JScrollPane(displayArea); 
     monoCard.add(monoScrollPane);
  monoCard.add(outputArea);
  monoCard.add(subPanel);
  monoCard.add(shiftButton);
  monoCard.add(clearButton);
  monoCard.add(distButton);
  monoCard.add(digramButton);
  monoCard.add(affineButton);

  //end of monoCard setup *************************
  
  //*********************************************************************
  
  //setup vigCard *********************************
     
    vigDisplayArea = new JTextArea(30,100);
    vigDisplayArea.setFont(new Font("monospaced",Font.PLAIN,12));

     vigSelectSubalphaButton = new JButton("Select Number of Subalphabets");
        vigSelectSubalphaButton.addActionListener(
          new ActionListener(){
            public void actionPerformed(ActionEvent event){
              String s = JOptionPane.showInputDialog(null,"Enter Number of Subalphabets");            
              int n = Integer.parseInt(s);
              if (n>0){
                vigSubalphabets = n;
                vigShowText();
              }
            }
           }
        );   

   vigICButton = new JButton("Show I.C. for Subalphabets");
   VigICHandler vigICHandler = new VigICHandler();
   vigICButton.addActionListener(vigICHandler);

   vigMakeShiftButton = new JButton("Make a Shift Substitution for a Subalphabet");
   VigShiftHandler vigShiftHandler = new VigShiftHandler();
   vigMakeShiftButton.addActionListener(vigShiftHandler);
   
   vigCompareButton = new JButton("Compare Subalphabets");
   VigCompareHandler vigCompareHandler = new VigCompareHandler();
   vigCompareButton.addActionListener(vigCompareHandler);
   
   vigDistButton = new JButton("Show Subalphabet Distribution");
   VigDistHandler vigDistHandler = new VigDistHandler();
   vigDistButton.addActionListener(vigDistHandler);

   vigClearButton = new JButton("Clear Guesses");
   VigClearHandler vigClearHandler = new VigClearHandler();
   vigClearButton.addActionListener(vigClearHandler);
   
   vigScrollPane = new JScrollPane(vigDisplayArea);
   vigCard.add(vigScrollPane);
   vigCard.add(vigSelectSubalphaButton);
   vigCard.add(vigDistButton);
   vigCard.add(vigICButton);
   vigCard.add(vigMakeShiftButton);
   vigCard.add(vigCompareButton);
   vigCard.add(vigClearButton);
   vigShowText();
   
     //end of vigCard setup **************************
  
  //*********************************************************************
  
     //setup diCard **********************************
     
        diDisplayArea = new JTextArea(30,100);
        diDisplayArea.setFont(new Font("monospaced",Font.PLAIN,12));
        
        diDigramButton = new JButton("Digram Distribution");
        diDigramButton.addActionListener(
          new ActionListener(){
            public void actionPerformed(ActionEvent event){
              int[][] diCount = new int[26][26];
              for(int i=0;i<26;i++)
                for(int j=0;j<26;j++)
                  diCount[i][j] = 0;
              int i=0;
              while(i<cipherText.length()-1){
                diCount[cipherText.charAt(i) - 'a'][cipherText.charAt(i+1) - 'a']++;
                i += 2;
              }
              String s = new String("");
              s = "     A    B    C    D    E    F    G    H    I    J    K    L    M";
              s += "    N    O    P    Q    R    S    T    U    V    W    X    Y    Z\n";
              for(i=0;i<26;i++){
                s+=Character.toString((char)('A' + i));
                for(int j=0;j<26;j++)
                  s +=" " + padOutput(diCount[i][j]) + diCount[i][j];
                  s += "\n";
              }
              double f = 0;
              int total = 0;
              for(i=0; i<26;i++)
                for(int j=0;j<26;j++){
                  f += diCount[i][j]*(diCount[i][j]-1);
                  total += diCount[i][j];
                }
              f /= total*(total-1);
            NumberFormat form = NumberFormat.getInstance(); //format for ic
              form.setMaximumFractionDigits(5);
               
              s += "\n Digram roughness: "+form.format(f)+"\n";
              //display
              DigramFrame digramFrame = new DigramFrame(s);
           }
          }
        );
 
        //setup Jpanel for Hill substitution
        JPanel diSubPanel = new JPanel();
        diSubPanel.setLayout(new FlowLayout());
        diSubPanel.setBackground(diColor);
        
        JLabel diPromptLabel1 = new JLabel("a:");
        diInputField1 = new JTextField(2);
        
        JLabel diPromptLabel2 = new JLabel("b:");
        diInputField2 = new JTextField(2);
 
        JLabel diPromptLabel3 = new JLabel("c:");
        diInputField3 = new JTextField(2);
        
        JLabel diPromptLabel4 = new JLabel("d:");
        diInputField4 = new JTextField(2);
        
        JButton diSubButton = new JButton("Make Hill Substitution");
        
        diSubButton.addActionListener(
          new ActionListener(){
            public void actionPerformed(ActionEvent event){
              String s1, s2, s3, s4;
              int a,b,c,d;
              s1 = diInputField1.getText();  //a input
              s2 = diInputField2.getText();  //b input
              s3 = diInputField3.getText();  //c input
              s4 = diInputField4.getText();  //d input
              //only make sub if data entered
              if(s1.length()>0 && s2.length()>0){
                a = Integer.parseInt(s1);
                b = Integer.parseInt(s2);
                makeDiSubab(a,b);
                diShowText();
                diInputField1.setText("");
                diInputField2.setText("");
              }
             if(s3.length()>0 && s4.length()>0){
                c = Integer.parseInt(s3);
                d = Integer.parseInt(s4);
                makeDiSubcd(c,d);
                diShowText();
                diInputField3.setText("");
                diInputField4.setText("");
              }
            }
          }
        );
        
        JButton diClearButton = new JButton("Clear Quesses");

        diClearButton.addActionListener(
          new ActionListener(){
            public void actionPerformed(ActionEvent event){
              for(int i=0;i<diSubText.length();i++)
                diSubText.setCharAt(i,'*');
              diShowText();
            }
          }
         );
  
        JButton diSubHelpButton = new JButton("Help");
        diSubHelpButton.addActionListener(
          new ActionListener(){
            public void actionPerformed(ActionEvent event){
               JOptionPane.showMessageDialog(null,
                 "Hill digram decryption method:\n"+
                 "digram c1 c2 decrypted as p1 p2, where\n\n"+
                 "p1 = a * c1 + b* c2\n"+
                 "p2 = c* c1 + d * c2\n\n"+
                 "Enter either a and b or\n  c and d.\n");
              }
            }
        );
          
        
        diSubPanel.add(diPromptLabel1);
        diSubPanel.add(diInputField1);
        diSubPanel.add(diPromptLabel2);
        diSubPanel.add(diInputField2);
        diSubPanel.add(diPromptLabel3);
        diSubPanel.add(diInputField3);
        diSubPanel.add(diPromptLabel4);
        diSubPanel.add(diInputField4);
        diSubPanel.add(diSubButton);
        diSubPanel.add(diSubHelpButton);
       
     
        diCard.add(new JScrollPane(diDisplayArea));
        diCard.add(diDigramButton);
        diCard.add(diSubPanel);
        diCard.add(diClearButton);
       
     //end of diCard setup****************************
  
  //*********************************************************************
  
     //set of colCard*********************************
       colDisplayArea = new JTextArea(30,100);
       colDisplayArea.setFont(new Font("monospaced",Font.PLAIN,12));
       
       JButton pickColsButton = new JButton("Select Number of Columns");
       pickColsButton.addActionListener(
          new ActionListener(){
            public void actionPerformed(ActionEvent event){
              int n;
              String s;
              s = JOptionPane.showInputDialog(null,"Enter number of columns");
              n = Integer.parseInt(s);
              if (cipherText.length()%n != 0)
                JOptionPane.showMessageDialog(null,
                   n + " does not divide " + cipherText.length());
              else{
                columns = n;
                colShowText();
              }
            }
            }
        );
      
       JButton restoreButton = new JButton("Restore Original");
       restoreButton.addActionListener(
          new ActionListener(){
            public void actionPerformed(ActionEvent event){
              for(int i=0;i<cipherText.length();i++)
                colText.setCharAt(i,cipherText.charAt(i));
              colShowText();
            }
          }
        );
      
       JButton permuteButton = new JButton("Permute Columns");
       permuteButton.addActionListener(
          new ActionListener(){
            public void actionPerformed(ActionEvent event){
              String s;
              s = JOptionPane.showInputDialog(null,
                     "Enter permutation of columns (1.."+
                     columns+")\n" +
                     "separated by spaces\n For example, 2 3 4 1 5 is a\n" +
                     "permutation if the number of columns\n"+
                     "is 5: ");
              permuteColumns(s);
            }
          }
        );
          
       JButton factorButton = new JButton("Factor Ciphertext Length");
       factorButton.addActionListener(
          new ActionListener(){
            public void actionPerformed(ActionEvent event){
              factor(colText.length());
            }
          }
        );

       colCard.add(new JScrollPane(colDisplayArea));
       colCard.add(factorButton);
       colCard.add(pickColsButton);
       colCard.add(restoreButton);
       colCard.add(permuteButton);
       colShowText();
       
     //end of colCard setup***************************
  
  //*********************************************************************
  
  //put deck in the container
  container.add(deck);

  setSize(800,650);
  setResizable(true);
  setVisible(true);

  }  //end of CipherBuddy constructor **************************************
  
  //*********************************************************************
 
  // routines and handlers for menu items - file I/O and mode buttons ***
    
  // action listener for cardlayout *************************************
  // switch modes between mono, vigenere, digram and columnar
  private class ModeHandler implements ActionListener {
    public void actionPerformed(ActionEvent event) {
      if(monoButton.isSelected()){
        cardManager.show(deck,"mono");
        mode = 0;
        setTitle("CipherBuddy - Mono Substitution");
        return;
      }
      if(vigButton.isSelected()){
        cardManager.show(deck,"vigenere");
        vigShowText();
        mode = 1;
        setTitle("CipherBuddy - Vigenere");
        return;
      }
      if(diButton.isSelected()){
        cardManager.show(deck,"digram");
        diShowText();
        mode = 2;
        setTitle("CipherBuddy - Digram");
        return;
      }
      if(colButton.isSelected()){
        cardManager.show(deck,"columnar");
        mode = 3;
        setTitle("CipherBuddy - Columnar");
        return;
      }
    }
  }

   //save plaintext in a file*********************************
    public void saveTheFile(String to_name)
      throws IOException {
      File to_file = new File(to_name);
     
      if(to_file == null ||
           to_file.getName().equals(""))
        JOptionPane.showMessageDialog(null,
          "Invalid file name");
      else{
        FileWriter to = null;
        //open file
        try{ 
          to = new FileWriter(to_file);
          char[] outArray = new char[subText.length()];
          if(mode ==0){
            for(int i=0;i<subText.length();i++)
              outArray[i] = subText.charAt(i);
            to.write(outArray,0,subText.length());
          }
          else if (mode == 1){
            for(int i=0;i<vigSubText.length();i++)
              outArray[i] = vigSubText.charAt(i);
            to.write(outArray,0,vigSubText.length());
          }
          else if (mode ==2){
            for(int i=0;i<diSubText.length();i++)
              outArray[i] = diSubText.charAt(i);
            to.write(outArray,0,diSubText.length());
          }
          else if (mode ==3){    //must save this by rows
            if(columns==0) return;
            int k=0;
            int rows = colText.length()/columns;
            for(int j=0;j<rows;j++)
              for(int i=0;i<columns;i++)
                outArray[k++] = colText.charAt(j + i*rows);
            to.write(outArray,0,colText.length());
          }
        }
        finally {
          if(to !=null) try {to.close();} catch(IOException e) {;}
        }
      }
    }
   
   //read the file and display *********************************
    public void readTheFile(String from_name)
      throws IOException {
      File from_file = new File(from_name);
   
   if(!from_file.exists())
   abhort("no such file: " + from_name);
   if (!from_file.isFile())
  abhort("can't copy directory: " + from_name);
   if (!from_file.canRead())
  abhort("source file is unreadable: " + from_name);
  
        //if got here, we're ready to copy
        columns = 0;   //reset no of columns
     FileReader from = null;
     try {
       from = new FileReader(from_file);
       char[] buffer = new char[80];
       int bytes_read;

       int j = 0;
       
       while ((bytes_read = from.read(buffer)) != -1) {
         String s = new String(buffer,0,bytes_read);
         cipherText.setLength(cipherText.length()+bytes_read);
         for(int i=0;i<bytes_read;i++)
            if(Character.isLetter(s.charAt(i))){
              cipherText.setCharAt(j,Character.toLowerCase(s.charAt(i)));
              j++;
            }
       }

       cipherText.setLength(j);
       colText.setLength(j);
       for(int i=0;i<j;i++)
             colText.setCharAt(i,cipherText.charAt(i));

       subText.setLength(cipherText.length());
       vigSubText.setLength(cipherText.length());
       diSubText.setLength(cipherText.length());
       colText.setLength(cipherText.length());
       for(int i=0;i<cipherText.length();i++){
         subText.setCharAt(i,'*');        //init plaintext for mono
         vigSubText.setCharAt(i,'*');     //init plaintext for vigenere
         diSubText.setCharAt(i,'*');      //init plaintext for digram
       }
       ShowText();
       vigShowText();
       diShowText();
       colShowText();
     }
     finally {
       if (from != null) try {from.close();} catch (IOException e) {;}
        }

      clearGuesses();
      return;
    }

 private static void abhort(String msg) throws IOException {
   JOptionPane.showMessageDialog(null,"FileCopy: "+ msg);
   throw new IOException("FileCopy: " + msg);
    }
 // end of menu routines ******************************************
 
 // ***************************************************************
 
 // mono routines and handlers ************************************

    //action listner for Affine button ********************************
    private class AffineHandler implements ActionListener {
    public void actionPerformed(ActionEvent event) {
     AffineFrame affineFrame= new AffineFrame();
     }
    }
              
    class AffineFrame extends JFrame  {
           
      private JLabel myHeader, myHeader1, myHeader2;
      private JTextField inField1, inField2;
      private String s1, s2;
      private JButton cancelButton, okButton; 

      public AffineFrame(){
        super("AffineSubstitution");

        Container container = getContentPane();
        container.setLayout(new FlowLayout());

        //set up buttons
        cancelButton = new JButton("Cancel");
        okButton = new JButton("OK");

        cancelButton.addActionListener(
          new ActionListener(){
            public void actionPerformed(ActionEvent event){
              setVisible(false);        
            }
          } 
        );

        okButton.addActionListener(
          new ActionListener(){
            public void actionPerformed(ActionEvent event){
              s1 = inField1.getText();
              s2 = inField2.getText();
              if (s1 != null && s2 != null){
               try{
                int m = Integer.parseInt(s1);
                int shift = Integer.parseInt(s2);
                if(m !=1 && m!=3 && m!=5 && m!=7 && m!=11 && m!=15 && 
                   m!=17 && m!=19 && m!=21 && m!=23 && m!=25) return;
                clearGuesses();
                if(shift<0) shift = 26 + shift;
                shift = shift % 26;
                for(int i=0;i<cipherText.length();i++)
                  subText.setCharAt(i,(char)((m*(cipherText.charAt(i) - 'a' + 1) - 1 + shift)%26 + 'A'));
                for(int i=0;i<26;i++)
                  subString.setCharAt(i, (char)((m*(i+1)-1+shift)%26 + 'A'));
                ShowSubstitution();
                ShowText();
                setVisible(false);
               }catch(NumberFormatException e){}
              }
             }
           }
         );

         //layout the frame
         myHeader = new JLabel("Make substitution m*C+s=P");
         myHeader1 = new JLabel("Multiplier:");
         myHeader2 = new JLabel("Shift:");
         inField1 = new JTextField(2);
         inField2 = new JTextField(2);
         container.add(myHeader);
         container.add(myHeader1);
         container.add(inField1);
         container.add(myHeader2);
         container.add(inField2);
         container.add(cancelButton);
         container.add(okButton);
         setSize(200,110);
         setResizable(false);
         setVisible(true);

       } //end of constructor
     }  //end of class AffineFrame 
    
  
    //action listner for shift button ********************************
    private class ShiftHandler implements ActionListener {
    public void actionPerformed(ActionEvent event) {
     SubFrame subFrame= new SubFrame();
     }
    }
              
    class SubFrame extends JFrame  {
           
      private JLabel myHeader1, myHeader2;
      private JTextField inField1, inField2;
      private String s1, s2;
      private JButton cancelButton, okButton; 

      public SubFrame(){
        super("Shift Substitution");

        Container container = getContentPane();
        container.setLayout(new FlowLayout());

        //set up buttons
        cancelButton = new JButton("Cancel");
        okButton = new JButton("OK");

        cancelButton.addActionListener(
          new ActionListener(){
            public void actionPerformed(ActionEvent event){
              setVisible(false);        
            }
          } 
        );

        okButton.addActionListener(
          new ActionListener(){
            public void actionPerformed(ActionEvent event){
              s1 = inField1.getText();
              s2 = inField2.getText();
              if (s1 != null && s2 != null){
                char c1 = Character.toLowerCase(s1.charAt(0));
                char c = Character.toLowerCase(s2.charAt(0));
                if (!Character.isLetter(c) || !Character.isLetter(c1)) return; 
                clearGuesses();
                int shift = c - c1;
                if(shift<0) shift = 26 + shift;
                for(int i=0;i<cipherText.length();i++)
                  subText.setCharAt(i,(char)((cipherText.charAt(i) - 'a' + shift)%26 + 'A'));
                for(int i=0;i<26;i++)
                  subString.setCharAt(i, (char)((i+shift)%26 + 'A'));
                ShowSubstitution();
                ShowText();
                setVisible(false);
              }
             }
           }
         );

         //layout the frame
         myHeader1 = new JLabel("Ciphertext");
         myHeader2 = new JLabel("should be shifted to plaintext");
         inField1 = new JTextField(1);
         inField2 = new JTextField(1);
         container.add(myHeader1);
         container.add(inField1);
         container.add(myHeader2);
         container.add(inField2);
         container.add(cancelButton);
         container.add(okButton);
         setSize(350,100);
         setResizable(false);
         setVisible(true);

       } //end of constructor
     }  //end of class SubFrame 
    
     //clear all substitutions for monoalphabet ***********************
     public void clearGuesses(){
       for(int i=0;i<26;i++) subString.setCharAt(i,' ');
       ShowSubstitution();
       for(int i=0;i<cipherText.length();i++)
         subText.setCharAt(i,'*');
     }
  
 //this displays the ciphertext (cipherText) and the 
 // corresponding plaintext (subText) in displayArea
 private void ShowText(){
   int textWidth = 100, j=0, i=0, lineLength=0;
   StringBuffer displayText = new StringBuffer("");
   
   displayArea.setText("");
   
   for(i=0;i<subText.length();i++){
     if(lineLength == textWidth){
       lineLength = 0;
       displayArea.append("\n");
       while(lineLength<textWidth){
         lineLength++;
         displayArea.append(Character.toString(cipherText.charAt(j)));
         j++;
       }
       displayArea.append("\n\n");
       lineLength=0;
     }
     displayArea.append(Character.toString(subText.charAt(i)));
     lineLength++;
   }
   displayArea.append("\n");
   //display last line of cipherText
   lineLength = 0;
   while(j<cipherText.length()){
     lineLength++;
     displayArea.append(Character.toString(cipherText.charAt(j)));
     j++;
   }
   displayArea.append("\n");
   displayArea.setCaretPosition(0);
 }
    
    //make the mono substitution ********************************************
    //modified 8 aug 2006
 public void makeSub(char a, char b){

      //if b is not a letter, ignore
      if (b != ' ' && !Character.isLetter(b)){
      //  inputField1.setText("");
        inputField2.setText("");
        return;
      }

      //1st make sure letter hasn't been used before
      for(int i=0;i<26;i++)
        if(b != ' ' && subString.charAt(i) == b) {
          inputField1.setText("");
       inputField2.setText("");
          JOptionPane.showMessageDialog(null,"Letter " + Character.toString(b) + " already used.");
          return;
        }
        
      if(b==' ') b = '*';

      for(int i=0;i<cipherText.length();i++) {
        if(cipherText.charAt(i) == a) subText.setCharAt(i,Character.toUpperCase(b));
      }
      ShowText();
   inputField1.setText("");
   inputField2.setText("");
   if(b=='*') b=' ';
   subString.setCharAt(a-'a',b);
   ShowSubstitution();
 }
 
 //show what substitutions have been made on outputArea display **************
 public void ShowSubstitution() {
   StringBuffer s = new StringBuffer("                                                   ");
   
   for(int i=0;i<26;i++)
     s.setCharAt(i*2,Character.toUpperCase(subString.charAt(i)));
   
   outputArea.setText(s.toString() + "\n" + alphaString.toString());
 }
 // end of mono section *****************************************************
 
 // *************************************************************************
 
 // columnar routines and handlers ******************************************
  //display text on columnar card
    public void colShowText(){
       int textWidth = 100;
     
       colDisplayArea.setText("");
     
       if(columns ==0){ //no columns set yet
         colDisplayArea.append("Number of columns not yet selected");
       }
       else {
         int jump = cipherText.length()/columns;
         for(int i=0;i<jump;i++){
           for(int j=i;j<cipherText.length();j += jump)
             colDisplayArea.append(Character.toString(colText.charAt(j)));
           colDisplayArea.append("\n");
         }
       }
       colDisplayArea.setCaretPosition(0);
    }
 
    //factor integer n****************************************
    public void factor(int n){
      int i=2,m=n;
      String s = new String("Length "+m+" has factors\n");
      while(i<=m/2){
        if(m%i==0)
          s += i+" ";
        i++;
      }
      JOptionPane.showMessageDialog(null,s);
    }
    
    //permute columns (columnar) *****************************
    public void permuteColumns(String s){
      int[] perm = new int[columns];
      int k=0,num=0;
 
      if(s==null) return;  //handle CANCEL button case

      for(int i=0; i<s.length();i++){
        if(Character.isDigit(s.charAt(i)))
          num = num*10 + Integer.parseInt(Character.toString(s.charAt(i)));
        else{
          if(num>0){
            if(k==columns){
             JOptionPane.showMessageDialog(null,"Too many numbers in the permutation "+s);
             return;
            }
            perm[k] = num;
            k++;
            num=0;
          }
          else
            JOptionPane.showMessageDialog(null,"Illegal permutation: "+s);
        }
      }
      //finish off last number
      if(k==columns){
        JOptionPane.showMessageDialog(null,"Too many numbers in the permutation "+s);
        return;
      }
      if(num>0){
        perm[k]=num;
        k++;
      }
      if(k!=columns){
        JOptionPane.showMessageDialog(null,"Too few numbers in the permutation "+s);
        return;
      }
      //check that all numbers within range
      for(int i=0;i<columns;i++)
        if(perm[i]<1 || perm[i]>columns){
          JOptionPane.showMessageDialog(null,"Numbers in permutation out of range "+s);
          return;
        }
      //now check that no column used more than once
      for(int i=0;i<columns;i++)
        for(int j=i+1;j<columns;j++)
          if(perm[i]==perm[j]){
            JOptionPane.showMessageDialog(null,"Number repeated "+s);
            return;
          }
      //if we got to here, we've got a legal permutation
      StringBuffer temp = new StringBuffer("");
      temp.setLength(colText.length());
      int jump = colText.length()/columns;   //jump = # of rows
      for(int j=0;j<columns;j++)
        for(int i=0;i<jump;i++){
          temp.setCharAt(j*jump+i, colText.charAt(i+(perm[j]-1)*jump));
        }        
      //copy temp back to colText;
      for(int i=0;i<colText.length();i++)
       colText.setCharAt(i,temp.charAt(i));
      colShowText();
    }

 // end of columnar section ******************************************************
 
 // ****************************************************************************
 
 // vigenere subroutines and handlers
   
     //action listner for vigenere shift button ********************************
     private class VigShiftHandler implements ActionListener {
    public void actionPerformed(ActionEvent event) {
      int n=0;
      while (n<1 || n>vigSubalphabets){
        String s = JOptionPane.showInputDialog(
           "Enter which subalphabet to shift (1-"+vigSubalphabets+"):");
        if(s==null) return;
        n = Integer.parseInt(s);
      } 
      String s = JOptionPane.showInputDialog(
              "Ciphertext letter A should shift to letter");
              if (s != null){
                char c = s.charAt(0);
                int shift = c-'a';
                for(int i=n-1;i<cipherText.length();i+=vigSubalphabets)
                  vigSubText.setCharAt(i,(char)((cipherText.charAt(i) - 'a' + shift)%26 + 'A'));
                vigShowText();
              }
            }
          }  

    //action listner for vigenere shift button ********************************
     private class VigCompareHandler implements ActionListener {
    public void actionPerformed(ActionEvent event) {
    //get subalphabets
      int n=0;
      while (n<1 || n>vigSubalphabets){
        String s = JOptionPane.showInputDialog(
           "Enter first subalphabet (1-"+vigSubalphabets+"):");
        if(s==null) return;
        n = Integer.parseInt(s);
      } 
      int m=0;
      while (m<1 || m>vigSubalphabets){
        String s = JOptionPane.showInputDialog(
           "Enter second subalphabet (1-"+vigSubalphabets+"):");
        if(s==null) return;
        m = Integer.parseInt(s);
      } 
           //now calculate letter counts for these 2 subalphabets
           int[] count1 = new int[26];
           int[] count2 = new int[26];
           for(int i=0;i<26;i++)
             count1[i]=count2[i]=0;
           for(int i=n-1;i<cipherText.length();i+=vigSubalphabets)
             count1[cipherText.charAt(i)-'a']++;
          for(int i=m-1;i<cipherText.length();i+=vigSubalphabets)
             count2[cipherText.charAt(i)-'a']++;
           String s = new String("If 'A' of subalphabet "+n+"\ncorresponds to given"
             + " letter\nof subalphabet "+m+":\n\n");
           for(int j=0;j<26;j++){
             int f = 0;
             for(int i=0;i<26;i++)
               f += count1[i]*count2[(i+j) % 26];
               s += Character.toString((char)(j+'a'))+": "+f+"\n";
            }
            VigCompareFrame vigCompareFrame = new VigCompareFrame(s);
    }
     }


     //action listenr for vigenere distributiton button
     private class VigDistHandler implements ActionListener{
         public void actionPerformed(ActionEvent event){
      int n=0;
      while (n<1 || n>vigSubalphabets){
              String s = JOptionPane.showInputDialog(
                "Show distribution for which subalphabet (1 -"+vigSubalphabets+")");
        if(s==null) return;
        n = Integer.parseInt(s);
      } 
              int[] count = new int[26];
              for(int i=0;i<26; i++) count[i]=0;
              for(int i=n-1; i<cipherText.length();i += vigSubalphabets) {
                int c=cipherText.charAt(i)-'a';
                count[c]++;
              }
              String s = new String(" Subalphabet "+n+"\n");
              String alphabet = new String("abcdefghijklmnopqrstuvwxyz");
              for(int i=0; i<26;i++){
                s = s +  Character.toString(alphabet.charAt(i)) + " " +
                count[i] + "\n";
              }
              //compute ic
             
              double ic=0;
              int total = 0;
              for(int i=0;i<26;i++){
                total += count[i];
                ic += count[i]*(count[i]-1);
              }
              ic = ic/(total*(total -1));
              s += " size = "+total+"\n";
              DistFrame distFrame =  new DistFrame(ic,s);
         }
     }
   
     //action listner for vigenere shift button ********************************
     private class VigClearHandler implements ActionListener {
    public void actionPerformed(ActionEvent event) {
            for(int i=0;i<cipherText.length();i++)
              vigSubText.setCharAt(i,'*');
            vigShowText();
          }
     }
 
    //action listener for vigenere shoe IC button
    private class VigICHandler implements ActionListener {
      public void actionPerformed(ActionEvent event) {
        VigICFrame vigICFrame = new VigICFrame(vigSubalphabets,cipherText.toString());
      }
    }
    
    //this displays the ciphertext (cipherText) and the corresponding plaintext (subText) in vigDisplayArea
 private void vigShowText(){
   int textWidth = 100, j=0, i=0, lineLength=0, charLength=0;
   StringBuffer displayText = new StringBuffer("");
   
   vigDisplayArea.setText("");
   
   for(i=0;i<vigSubText.length();i++){
     if(lineLength == textWidth){
       lineLength = 0;
       vigDisplayArea.append("\n");
       while(lineLength<textWidth){
         lineLength++;
         vigDisplayArea.append(Character.toString(cipherText.charAt(j)));
         j++;
       }
       vigDisplayArea.append("\n");
       lineLength=0;
       while(lineLength<textWidth){
         if(vigSubalphabets == 1)
           vigDisplayArea.append("^");
         else if(charLength % vigSubalphabets == 0)
           vigDisplayArea.append("^");
         else
           vigDisplayArea.append(" ");
            lineLength++;
            charLength++;
       }
       vigDisplayArea.append("\n");
       lineLength = 0;
     }
     vigDisplayArea.append(Character.toString(vigSubText.charAt(i)));
     lineLength++;
   }
   vigDisplayArea.append("\n");
   //display last line of cipherText
   lineLength = 0;
   while(j<cipherText.length()){
     lineLength++;
     vigDisplayArea.append(Character.toString(cipherText.charAt(j)));
     j++;
   }
   vigDisplayArea.append("\n");
   //display last line of carets
      lineLength=0;
      while(charLength<cipherText.length()){
        if(vigSubalphabets ==1)
          vigDisplayArea.append("^");
        else if(charLength % vigSubalphabets == 0)
          vigDisplayArea.append("^");
        else
          vigDisplayArea.append(" ");
        lineLength++;
        charLength++;
      }
   vigDisplayArea.append("\n");
   vigDisplayArea.setCaretPosition(0); 
 }

 // end of vigenere section ***************************************

 // ***************************************************************
 
 // routines and handlers for digram card *************************
 
 //padding for digram output: add extra spaces as needed **********
     public String padOutput(int x){
  //     if(x>999) return(" ");
       if(x>99) return(" ");
       if(x>9) return("  ");
       return("   ");
     }
     
 //this displays the ciphertext (cipherText) and the corresponding plaintext (subText) in displayArea
 private void diShowText(){
   int textWidth = 100, j=0, i=0, lineLength=0, charLength=0;
   
   diDisplayArea.setText("");
   
   for(i=0;i<subText.length();i++){
     if(lineLength == textWidth){
       lineLength = 0;
       diDisplayArea.append("\n");
       while(lineLength<textWidth){
         lineLength++;
         diDisplayArea.append(Character.toString(cipherText.charAt(j)));
         j++;
       }
       diDisplayArea.append("\n");
       lineLength=0;
       while(lineLength<textWidth){
         if(charLength % 2 == 0)
           diDisplayArea.append("^");
         else
           diDisplayArea.append(" ");
            lineLength++;
            charLength++;
       }
       diDisplayArea.append("\n");
       lineLength=0;
     }
     diDisplayArea.append(Character.toString(diSubText.charAt(i)));
     lineLength++;
   }
   diDisplayArea.append("\n");
   //display last line of cipherText
   lineLength = 0;
   while(j<cipherText.length()){
     lineLength++;
     diDisplayArea.append(Character.toString(cipherText.charAt(j)));
     j++;
   }
   diDisplayArea.append("\n");
   //display last line of carets
      lineLength=0;
      while(charLength<cipherText.length()){
        if(charLength % 2 == 0)
          diDisplayArea.append("^");
        else
          diDisplayArea.append(" ");
        lineLength++;
        charLength++;
      }
   diDisplayArea.append("\n");

   diDisplayArea.setCaretPosition(0);
 }

    //make digram sub for first letter of pair 
 private void makeDiSubab(int a, int b)
 {
   int i=0;
   while(i<cipherText.length()-1){
     int c1, c2;
     c1 = (int)(cipherText.charAt(i)-'a')+1;
     c2 = (int)(cipherText.charAt(i+1)-'a')+1;
     char p1,p2;
     int x = (c1*a + c2*b) % 26;
     x--;
     if(x<0) x=25;
     p1 = (char)(x + 'A');
     diSubText.setCharAt(i,p1);
     i++; i++;
   }
 }

    //make digram sub for 2nd letter of pair
 private void makeDiSubcd(int a, int b)
 {
   int i=0;
   while(i<cipherText.length()-1){
     int c1, c2;
     c1 = (int)(cipherText.charAt(i)-'a')+1;
     c2 = (int)(cipherText.charAt(i+1)-'a')+1;
     char p1,p2;
     int x = (c1*a + c2*b) % 26;
     x--;
     if(x<0) x=25;
     p1 = (char)(x + 'A');
     diSubText.setCharAt(i+1,p1);
     i++; i++;
   }
 }
 
public void DoSomething(char c){
 //set 'a' to 'X'
 subString.setCharAt(2, c);
 ShowSubstitution();
}

 // end of digram section **********************************
 
// class to display Frame showing digram distributions
// called by "Diagram Distribution" button on monoCard

class MyFrame extends JFrame {
	
   public String getInfo(String title, String message){
        // super(title);
        
        final String[] result = new String[1];

        Container container = getContentPane();
        container.setLayout(new FlowLayout());

        JLabel myPrompt = new JLabel(message);
        final JTextField myInputField = new JTextField(2);
        JButton cancelButton = new JButton("Cancel");
        JButton okButton = new JButton("OK");

        cancelButton.addActionListener(
         new ActionListener(){
          public void actionPerformed(ActionEvent event){
            setVisible(false);
            result[0] = "";
          }
         }
        );

        okButton.addActionListener(
         new ActionListener(){
          public void actionPerformed(ActionEvent event){
           String s = myInputField.getText();
            setVisible(false);
            result[0] = s;
          }
         }
        );
     

 	   container.add(myPrompt);
           container.add(myInputField);
           container.add(cancelButton);
           container.add(okButton);
	   setSize(250,120);
	   setResizable(false);
	   setVisible(true);
    
    return result[0];
	}
}
 // end of MyFrame (static method getInfo)

 // ********************************************************
   
 // main program *******************************************
 
 public static void main(String args[])
 {
   CipherBuddy app = new CipherBuddy();
   
   app.addWindowListener(
     new WindowAdapter() {
     public void windowClosing(WindowEvent windowEvent)
     {
       System.exit(0);
     }}
     );
  
 }
}

